﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace CoreLims.Models.CoreLims
{
    using TestDefinition = SampleTestDefinition;

    public static class SampleTestDefinitionExtension
    {
        public static List<TestDefinition> getTestDefinitionList(this TestDefinition tdf, CoreLimsContext dbContext) => dbContext.TestDefinition.ToList();

        /// <summary>
        /// 根据 一级分类 获取测试定义数据
        /// </summary>
        /// <param name="FirstGroup"></param>
        /// <returns></returns>
        public static List<TestDefinition> getTestDefinitionListByFirstGroup(this TestDefinition tdf, CoreLimsContext dbContext, string FirstGroup) =>
            dbContext.TestDefinition.Where(s => s.FirstGroup == FirstGroup).OrderBy(x => x.TestName).ToList();

        /// <summary>
        /// 根据 二级分类 获取测试定义数据
        /// </summary>
        /// <returns></returns>
        public static List<TestDefinition> getTestDefinitionListBySecondGroup(this TestDefinition tdf, CoreLimsContext dbContext, string SecondGroup) =>
            dbContext.TestDefinition.Where(s => s.SecondGroup == SecondGroup).OrderBy(x => x.TestName).ToList();

        /// <summary>
        /// 根据 一级、二级 分类，获取测试定义数据
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="dbContext"></param>
        /// <param name="FirstGroup">一级分类</param>
        /// <param name="SecondGroup">二级分类</param>
        /// <returns></returns>
        public static List<TestDefinition> getTestDefinitionListFirstAndBySecond(this TestDefinition tdf, CoreLimsContext dbContext, string FirstGroup, string SecondGroup)
        {
            if (FirstGroup == "全部")
                return dbContext.TestDefinition.OrderBy(x => x.TestName).ToList();

            if (string.IsNullOrEmpty(SecondGroup))
                return dbContext.TestDefinition.Where(s => s.FirstGroup == FirstGroup).OrderBy(x => x.TestName).ToList();
            else
                return dbContext.TestDefinition.Where(s => s.FirstGroup == FirstGroup && s.SecondGroup == SecondGroup).OrderBy(x => x.TestName).ToList();
        }

        public static List<TestDefinition> getTestDefinition(this TestDefinition tdf, CoreLimsContext dbContext) => 
            dbContext.TestDefinition.ToList().OrderBy(x => x.TestName).ToList();

        public static TestDefinition getTestDefinition(this TestDefinition tdf, CoreLimsContext dbContext, string Id) => 
            dbContext.TestDefinition.FirstOrDefault(m => m.Id == Id);

        /// <summary>
        /// 根据 测试定义名称 查询测试定义
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="dbContext"></param>
        /// <param name="Code"></param>
        /// <returns></returns>
        public static TestDefinition getTestDefinitionByCode(this TestDefinition tdf, CoreLimsContext dbContext, string TestName) => dbContext.TestDefinition.FirstOrDefault(m => m.TestName == TestName);

        /// <summary>
        /// 根据 名称 模糊查询
        /// </summary>
        /// <param name="TestName"></param>
        /// <returns></returns>
        public static List<TestDefinition> getTestDefinitionByName(this TestDefinition tdf, CoreLimsContext dbContext, string TestName) =>
            dbContext.TestDefinition.Where(m => m.TestName.Contains(TestName)).ToList().OrderBy(x => x.TestName).ToList();

        /// <summary>
        /// 添加 测试定义
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        public static string AddTestDefinition(this TestDefinition tdf, CoreLimsContext dbContext)
        {
            tdf.Id = SAMPLE._newId();
            tdf.ReleaseStatus = "Draft";
            tdf.Version = 1;
            dbContext.Add(tdf);
            dbContext.SaveChanges();
            return "测试定义添加成功！";
        }

        /// <summary>
        /// 更新测试定义
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="dbContext"></param>
        /// <param name="UpdateAll">如果更新所有项，UpdateAll=true 否则 =false </param>
        /// <returns></returns>
        public static string UpdateTestDefinition(this TestDefinition tdf, CoreLimsContext dbContext, Boolean UpdateAll = true)
        {
            TestDefinition Tdf = SAMPLE.TestDefinition.getTestDefinition(dbContext, tdf.Id);
            if (UpdateAll)
            {
                Tdf.Copy(tdf);
            }
            else
            {
                Tdf.CopyText(tdf);
            }

            dbContext.Update(Tdf);
            dbContext.SaveChanges();
            return "测试定义信息更新成功！";
        }

        public static string DeleteTestDefinition(this TestDefinition tdf, CoreLimsContext dbContext, string Id)
        {
            // 删除测试时，需要检查样品定义关系表，如果有样品对测试的引用，则不能删除测试。
            var sampleList = dbContext.Relation.Where(s => s.SourceTabName == "SampleDefinition" && s.IncludedId == Id).ToList();
            foreach (var sl in sampleList)
            {
                var sample = SAMPLE.SampleDefinition.getSampleDefinition(dbContext, sl.SourceId);
                return "当前测试与 " + sampleList.Count.ToString() + " 个样品定义有关联，不能被删除。第一个样品是：" + sample.Name;
            }

            TestDefinition Tdf = SAMPLE.TestDefinition.getTestDefinition(dbContext, Id);
            var relations = dbContext.TestRelation.Where(s => s.TestDefinitionId == Id).ToList();
            if(relations.Count > 0)
            {
                foreach(var rel in relations)
                {
                    dbContext.Remove(rel); // 删除当前测试的关联关系
                }
            }
            dbContext.Remove(Tdf);

            dbContext.SaveChanges();
            return "删除成功！";
        }

        /// <summary>
        /// 复制记录内容，ID不复制
        /// </summary>
        /// <param name="supplier"></param>
        /// <param name="other"></param>
        /// <returns></returns>
        public static TestDefinition Copy(this TestDefinition tdf, TestDefinition other)
        {
            tdf.TestName = other.TestName;
            tdf.FirstGroup = other.FirstGroup;
            tdf.SecondGroup = other.SecondGroup;
            tdf.Description = other.Description;
            tdf.Version = other.Version;
            tdf.ReleaseStatus = other.ReleaseStatus;

            return tdf;
        }

        /// <summary>
        /// 不包含 版本、状态
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="other"></param>
        /// <returns></returns>
        public static TestDefinition CopyText(this TestDefinition tdf, TestDefinition other)
        {
            tdf.TestName = other.TestName;
            tdf.FirstGroup = other.FirstGroup;
            tdf.SecondGroup = other.SecondGroup;
            tdf.Description = other.Description;

            return tdf;
        }

        /// <summary>
        /// 根据自身ID从 TestRelation 表中获得与自身关联的分析项列表
        /// </summary>
        /// <returns></returns>
        public static IQueryable<object> getTestDefinitionRelationAnalytes(this TestDefinition tdf, CoreLimsContext dbcontext) 
        {
            var list = dbcontext.TestRelation.Where(s => s.TestDefinitionId == tdf.Id)
                .Select(s => new { s.AnalytesId }).ToArray();

            string[] array = new string[list.Length];
            for (int i = 0; i < list.Length; i++)
            {
                array[i] = list[i].AnalytesId;
            }

            var analytelist = from analyte in dbcontext.Analyte
                              join test in dbcontext.TestRelation on analyte.Id equals test.AnalytesId
                              where (array.Contains(analyte.Id) && test.TestDefinitionId == tdf.Id)
                              select new { test.Id, analyte.Code, analyte.Name, analyte.Classification, analyte.Description,
                                  analyte.ResultModel, analyte.RoundingOff, analyte.Units,analyte.DefaultSpecName,analyte.Assist,
                                  test.DetectionTimes, test.AnalytesId };

            return analytelist;
        }

        public static IQueryable<object> getTestDefinitionRelationAnalytes(this TestDefinition tdf, CoreLimsContext dbcontext, string TestDefinitionID)
        {
            var list = dbcontext.TestRelation.Where(s => s.TestDefinitionId == TestDefinitionID)
                .Select(s => new { s.AnalytesId }).ToArray();

            string[] array = new string[list.Length];
            for (int i = 0; i < list.Length; i++)
            {
                array[i] = list[i].AnalytesId;
            }

            var analytelist = from analyte in dbcontext.Analyte
                              join test in dbcontext.TestRelation on analyte.Id equals test.AnalytesId
                              where (array.Contains(analyte.Id) && test.TestDefinitionId == TestDefinitionID)
                              select new
                              {
                                  test.Id,
                                  analyte.Code,
                                  analyte.Name,
                                  analyte.Classification,
                                  analyte.Description,
                                  analyte.ResultModel,
                                  analyte.RoundingOff,
                                  analyte.Units,
                                  analyte.DefaultSpecName,
                                  analyte.Assist,
                                  test.DetectionTimes,
                                  test.AnalytesId
                              };

            return analytelist;
        }

        /// <summary>
        /// 根据自身ID，从 TestRelation 表中获得与自身关联的指标集列表
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="dbcontext"></param>
        /// <returns></returns>
        public static IQueryable<object> getTestDefinitionRelationSpecCollection(this TestDefinition tdf, CoreLimsContext dbcontext)
        {
            var list = dbcontext.TestRelation.Where(s => s.TestDefinitionId == tdf.Id)
                .Select(s => new { s.SpecCollectionId }).ToArray();

            string[] array = new string[list.Length];
            for (int i = 0; i < list.Length; i++)
            {
                array[i] = list[i].SpecCollectionId;
            }

            var speclist = from spec in dbcontext.Spec
                              join test in dbcontext.TestRelation on spec.Id equals test.SpecCollectionId
                              where (array.Contains(spec.Id) && test.TestDefinitionId == tdf.Id)
                              select new
                              {
                                  test.Id,
                                  test.IsDefault,
                                  spec.Code,
                                  spec.Name,
                                  spec.Description,
                                  spec.FirstGroup,
                                  spec.SecondGroup,
                                  spec.Version,
                                  spec.ReleaseStatus,
                                  spec.Enable,
                                  test.SpecCollectionId
                              };

            return speclist;
        }

        /// <summary>
        /// 根据自身ID，从 TestRelation 表中获得与自身关联的方法列表
        /// </summary>
        /// <param name="tdf"></param>
        /// <param name="dbcontext"></param>
        /// <returns></returns>
        public static IQueryable<object> getTestDefinitionRelationMethod(this TestDefinition tdf, CoreLimsContext dbcontext)
        {
            var list = dbcontext.TestRelation.Where(s => s.TestDefinitionId == tdf.Id)
                .Select(s => new { s.MethodId }).ToArray();

            string[] array = new string[list.Length];
            for (int i = 0; i < list.Length; i++)
            {
                array[i] = list[i].MethodId;
            }

            var mlist = from method in dbcontext.Method
                           join test in dbcontext.TestRelation on method.Id equals test.MethodId
                           where (array.Contains(method.Id) && test.TestDefinitionId == tdf.Id)
                           select new
                           {
                               test.Id,
                               test.IsDefault,
                               method.Code,
                               method.Name,
                               method.Type,
                               method.Description,
                               method.EffectiveDate,
                               method.ExpireDate,
                               method.RecordSheet,
                               method.Version,
                               method.Status,
                               test.MethodId
                           };

            return mlist;
        }

    }

}
